import java.util.ArrayList;
import java.awt.Color;
import java.awt.Point;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

public class Grapher extends JFrame {
	protected static final int DIR_UP=0; 
	protected static final int DIR_RIGHT=1; 
	protected static final int DIR_DOWN=2; 
	protected static final int DIR_LEFT=3; 
	
	protected IGenGen gengen;
	protected boolean princess;
	protected JPanel draw;	
	protected IGenerator gen;
	ArrayList<Point> points;
	protected int dir=DIR_RIGHT;
	
	protected class MyPanel extends JPanel implements ComponentListener {
		public MyPanel() {
			addComponentListener(this);
		}
		
		@Override
		public void componentHidden(ComponentEvent e) {
		}
		
		@Override
		public void componentMoved(ComponentEvent e) {
		}
		
		@Override
		public void componentShown(ComponentEvent e) {
		}
		
		@Override
		public void componentResized(ComponentEvent e) {
			points.clear();
			points.add(new Point(draw.getWidth()/2, draw.getHeight()/2));
			gen = gengen.getOne();
			repaint();
		}
		
		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			if (points.isEmpty())
				return; //nothing to do
			Point last = points.get(0);
			g.setColor(princess ? Color.cyan : Color.red);
			for (Point pt: points) {
				g.drawLine((int)last.getX(), (int)last.getY(), (int)pt.getX(), (int)pt.getY());
				last = pt;
			}
		}
	}
	
	public Grapher(String title, IGenGen gg, boolean p) {
		gengen = gg;
		gen = gg.getOne();
		points = new ArrayList<Point>();
		princess = p;
		
		setSize(600,600);
		setTitle(title);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setLocation(200,200);

		JPanel btnF = new JPanel();
		btnF.setLayout(new BoxLayout(btnF, BoxLayout.X_AXIS));
		btnF.add(Box.createHorizontalGlue());
		JButton btnNext = new JButton("Next");
		btnNext.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				//JOptionPane.showMessageDialog(null, gen.next(), 
				//	"Nombre à dessiner", JOptionPane.INFORMATION_MESSAGE); 
				Point last = points.get(points.size()-1);
				int newX = (int)last.getX(), newY = (int)last.getY();
				switch (dir) {
					case DIR_UP:
						newY += gen.next();
						break;
					case DIR_RIGHT:
						newX += gen.next();
						break;
					case DIR_DOWN:
						newY -= gen.next();
						break;
					case DIR_LEFT:
						newX -= gen.next();
						break;
					default:
				}
				dir = (dir+1) % 4;
				points.add(new Point(newX, newY));
				//System.out.println("added "+points.get(points.size()-1).toString());
				draw.repaint();
			}
		});
		btnF.add(btnNext);
		btnF.add(Box.createHorizontalGlue());
		
		draw = new MyPanel();
		draw.setBackground(princess ? Color.pink : Color.white);

		add(Box.createVerticalStrut(10));
		setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
		add(btnF);
		add(Box.createVerticalStrut(10));
		add(draw);
		
		setVisible(true);
	}
	
	public static void main(String[] args)
	{
		Grapher gr = new Grapher("Spirale de Fibonacci", new IGenGen() {
			public IGenerator getOne() {
				return new Fibonacci();
			}
		}, false);
		
		Grapher gr2 = new Grapher("Spirale classique", new IGenGen() {
			public IGenerator getOne() {
				return new PlusOne();
			}
		}, false);
	}
}

